import { memo, useEffect, useRef, useState } from 'react';
import type { ReactNode, FC } from 'react';
import { PlayerBarListWrapper } from './style';
import { shallowEqualApp, useAppDispatch, useAppSelector } from '@/store/hooks';
import PlayerbarListItem from '../playerbarList-item';
import { deleteAllPlayerList } from '@/views/player/store/player';

interface IProps {
  children?: ReactNode;
  className?: string;
  setPlayerList: () => void;
}

const ITEM_HEIGHT = 30;
const LIST_VISIBLE_HEIGHT = 260;
const LYRIC_VISIBLE_HEIGHT = 210;

const PlayerbarList: FC<IProps> = (props) => {
  const { className, setPlayerList } = props;
  const dispatch = useAppDispatch();
  const { currentSong, songLists, lyric, lyricIndex } = useAppSelector(
    (state) => ({
      currentSong: state.player.currentSong,
      songLists: state.player.SongList,
      lyric: state.player.lyric,
      lyricIndex: state.player.lyricIndex,
    }),
    shallowEqualApp
  );

  // 歌曲列表滚动条
  const listRef = useRef<HTMLDivElement>(null);
  const [listScrollTop, setListScrollTop] = useState(0);
  const [listScrollBarHeight, setListScrollBarHeight] = useState(0);
  const [listScrollBarTop, setListScrollBarTop] = useState(0);
  const [listDragging, setListDragging] = useState(false);
  const listDragStartY = useRef(0);
  const listDragStartScrollTop = useRef(0);

  const listContentHeight = songLists.length * ITEM_HEIGHT;

  // 歌词滚动条
  const lyricRef = useRef<HTMLDivElement>(null);
  const [lyricScrollTop, setLyricScrollTop] = useState(0);
  const [lyricScrollBarHeight, setLyricScrollBarHeight] = useState(0);
  const [lyricScrollBarTop, setLyricScrollBarTop] = useState(0);
  const [lyricDragging, setLyricDragging] = useState(false);
  const lyricDragStartY = useRef(0);
  const lyricDragStartScrollTop = useRef(0);

  const lyricContentHeight = lyric.length * ITEM_HEIGHT;

  // 列表滚动条高度与位置
  useEffect(() => {
    const vis = LIST_VISIBLE_HEIGHT;
    const cont = listContentHeight;
    let barHeight = vis;
    if (cont > vis) barHeight = (vis / cont) * vis;
    setListScrollBarHeight(barHeight);
    setListScrollBarTop((listScrollTop / (cont - vis)) * (vis - barHeight) || 0);
  }, [songLists.length, listScrollTop, listContentHeight]);

  // 歌词滚动条高度与位置
  useEffect(() => {
    const vis = LYRIC_VISIBLE_HEIGHT;
    const cont = lyricContentHeight;
    let barHeight = vis;
    if (cont > vis) barHeight = (vis / cont) * vis;
    setLyricScrollBarHeight(barHeight);
    setLyricScrollBarTop((lyricScrollTop / (cont - vis)) * (vis - barHeight) || 0);
  }, [lyric.length, lyricScrollTop, lyricContentHeight]);

  // 列表拖拽
  const onListScrollBarMouseDown = (e: React.MouseEvent) => {
    setListDragging(true);
    listDragStartY.current = e.clientY;
    listDragStartScrollTop.current = listScrollTop;
    document.body.style.userSelect = 'none';
  };
  useEffect(() => {
    if (!listDragging) return;
    const barMovable = LIST_VISIBLE_HEIGHT - listScrollBarHeight;
    const maxScrollTop = listContentHeight - LIST_VISIBLE_HEIGHT;
    const onMouseMove = (e: MouseEvent) => {
      const deltaY = e.clientY - listDragStartY.current;
      let nextBarTop = Math.min(Math.max(listScrollBarTop + deltaY * (1 / songLists.length), 0), barMovable);
      let nextScrollTop = (nextBarTop / barMovable) * maxScrollTop;
      setListScrollTop(nextScrollTop);
    };
    const onMouseUp = () => {
      setListDragging(false);
      document.body.style.userSelect = '';
    };
    window.addEventListener('mousemove', onMouseMove);
    window.addEventListener('mouseup', onMouseUp);
    return () => {
      window.removeEventListener('mousemove', onMouseMove);
      window.removeEventListener('mouseup', onMouseUp);
    };
  }, [listDragging, listScrollBarHeight, listScrollBarTop, listContentHeight]);

  // 歌词拖拽
  const onLyricScrollBarMouseDown = (e: React.MouseEvent) => {
    setLyricDragging(true);
    lyricDragStartY.current = e.clientY;
    lyricDragStartScrollTop.current = lyricScrollTop;
    document.body.style.userSelect = 'none';
  };
  useEffect(() => {
    if (!lyricDragging) return;
    const barMovable = LYRIC_VISIBLE_HEIGHT - lyricScrollBarHeight;
    const maxScrollTop = lyricContentHeight - LYRIC_VISIBLE_HEIGHT;
    const onMouseMove = (e: MouseEvent) => {
      const deltaY = e.clientY - lyricDragStartY.current;
      let nextBarTop = Math.min(Math.max(lyricScrollBarTop + deltaY * (1 / lyric.length), 0), barMovable);
      let nextScrollTop = (nextBarTop / barMovable) * maxScrollTop;
      setLyricScrollTop(nextScrollTop);
    };
    const onMouseUp = () => {
      setLyricDragging(false);
      document.body.style.userSelect = '';
    };
    window.addEventListener('mousemove', onMouseMove);
    window.addEventListener('mouseup', onMouseUp);
    return () => {
      window.removeEventListener('mousemove', onMouseMove);
      window.removeEventListener('mouseup', onMouseUp);
    };
  }, [lyricDragging, lyricScrollBarHeight, lyricScrollBarTop, lyricContentHeight]);

  // 列表滚轮
  useEffect(() => {
    const el = listRef.current;
    if (!el) return;
    const handle = (e: WheelEvent) => {
      e.preventDefault();
      const maxScrollTop = listContentHeight - LIST_VISIBLE_HEIGHT;
      let nextScrollTop = listScrollTop + e.deltaY;
      nextScrollTop = Math.max(0, Math.min(nextScrollTop, maxScrollTop));
      setListScrollTop(nextScrollTop);
    };
    el.addEventListener('wheel', handle, { passive: false });
    return () => el.removeEventListener('wheel', handle);
  }, [listScrollTop, listContentHeight]);

  // 歌词滚轮
  useEffect(() => {
    const el = lyricRef.current;
    if (!el) return;
    const handle = (e: WheelEvent) => {
      e.preventDefault();
      const maxScrollTop = lyricContentHeight - LYRIC_VISIBLE_HEIGHT;
      let nextScrollTop = lyricScrollTop + e.deltaY;
      nextScrollTop = Math.max(0, Math.min(nextScrollTop, maxScrollTop));
      setLyricScrollTop(nextScrollTop);
    };
    el.addEventListener('wheel', handle, { passive: false });
    return () => el.removeEventListener('wheel', handle);
  }, [lyricScrollTop, lyricContentHeight]);

  // 歌词高亮自动滚动
  useEffect(() => {
    if (lyricIndex < 0) return;
    const target = Math.max(0, lyricIndex * ITEM_HEIGHT - LYRIC_VISIBLE_HEIGHT / 2 + ITEM_HEIGHT / 2);
    setLyricScrollTop(Math.min(target, lyricContentHeight - LYRIC_VISIBLE_HEIGHT));
  }, [lyricIndex, lyricContentHeight]);

  return (
    <PlayerBarListWrapper className={className}>
      <div className="listhd sprite_playerList">
        <h4>播放列表({songLists.length})</h4>
        <a href="javascript:void(0)" className="add">
          <span className="sprite_playerList_icon add_icon icon"></span>
          收藏全部
        </a>
        <span className="line">|</span>
        <a
          className="clear"
          onClick={(e) => {
            e.preventDefault();
            dispatch(deleteAllPlayerList());
          }}
        >
          <span className="sprite_playerList_icon clear_icon icon"></span>
          清除
        </a>
        <p className="name">{currentSong.name}</p>
        <span className="sprite_playerList_icon close" onClick={() => setPlayerList()}>
          关闭
        </span>
      </div>
      <div className="listbd sprite_playerList">
        <div className="msk"></div>
        {/* 歌曲列表滚动条 */}
        <div className="bline">
          <span
            className="scroll"
            style={{
              height: `${listScrollBarHeight}px`,
              top: `${listScrollBarTop}px`,
              cursor: listDragging ? 'grabbing' : 'grab',
            }}
            onMouseDown={onListScrollBarMouseDown}
          ></span>
        </div>
        <div className="ask">
          <a href="" className="ask_icon sprite_playerList_icon"></a>
        </div>
        <div className="scrolling">
          <span
            className="scroll"
            style={{
              height: `${lyricScrollBarHeight}px`,
              top: `${lyricScrollBarTop}px`,
              cursor: lyricDragging ? 'grabbing' : 'grab',
            }}
            onMouseDown={onLyricScrollBarMouseDown}
          ></span>
        </div>
        {/* 歌曲列表内容 */}
        <div
          className="songLists"
          ref={listRef}
          style={{
            height: `${LIST_VISIBLE_HEIGHT}px`,
            overflow: 'hidden',
            position: 'relative',
          }}
        >
          <div
            className="songLists-content"
            style={{
              transform: `translateY(-${listScrollTop}px)`,
              transition: listDragging ? 'none' : 'transform 0.15s',
              height: `${listContentHeight}px`,
            }}
          >
            {songLists.map((song, index) => (
              <PlayerbarListItem
                isPlaying={currentSong.name === song.name}
                song={song}
                currentIndex={index}
                key={index}
              />
            ))}
          </div>
        </div>
        {/* 歌词内容区域 */}
        <div
          className="lyric"
          ref={lyricRef}
          style={{
            height: `${LYRIC_VISIBLE_HEIGHT}px`,
            overflow: 'hidden',
          }}
        >
          <div
            className="lyric-content"
            style={{
              transform: `translateY(-${lyricScrollTop}px)`,
              transition: lyricDragging ? 'none' : 'transform 0.15s',
              height: `${lyricContentHeight}px`,
            }}
          >
            {lyric.map((item, index) => (
              <p key={item.time} className={lyricIndex === index ? 'active' : ''}>
                {item.lyric}
              </p>
            ))}
          </div>
        </div>
      </div>
    </PlayerBarListWrapper>
  );
};

export default memo(PlayerbarList);
